<?php

// 公共文件

if (!function_exists('json_string')) {
	function json_string($data, $pretty = false)
	{
		$pretty = !$pretty ? 1 : JSON_PRETTY_PRINT;
		return json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | $pretty);
	}
}

if (!function_exists('json_prin')) {
	/**
	 * 打印格式化数据
	 * @param $data
	 * @param int $exit
	 */
	function json_prin($data, $exit = false)
	{
		if (is_string($data)) {
			$array = json_decode($data, true);
			if (is_array($array)) $data = $array;
		}
		if (stripos(PHP_SAPI, 'cli') === false) echo '<pre>'.PHP_EOL;
		echo json_string($data) . PHP_EOL;
		if ($exit) exit(0);
	}
}

/**
 * 获取请求头
 * @return array
 *
 * ["User-Agent": "xxx", "Cookie": "PHPSID=39f24c20aa54d841131eeb6a"]
 */
function headers()
{
    if (function_exists('getallheaders')) {
        return getallheaders();
    }
    $headers = [];
    foreach ($_SERVER as $name => $value) {
        if (strpos($name, 'HTTP_') === 0) {
            $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
            $headers[$name] = $value;
        }
    }
    if (!isset($headers['Authorization'])) {
        if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
            $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
        } elseif (isset($_SERVER['PHP_AUTH_USER'])) {
            $basic_pass = $_SERVER['PHP_AUTH_PW'] ?? '';
            $headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass);
        } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
            $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST'];
        }
    }
    return $headers;
}



/**
 * 把任意类型的数据转化为字符串，用于记录日志
 * @param mixed $obj 可以是任意数据类型
 * @return string
 * @throws
 */
function to_string($obj)
{
    if (is_string($obj)) {
        return $obj;
    }
    if (is_numeric($obj)) {
        return (string) $obj;
    }
    if (is_null($obj)) {
        return 'NULL';
    }
    if (is_bool($obj)) {
        return $obj ? 'TRUE' : 'FALSE';
    }
    if ($obj instanceof Throwable) {
        $obj = filter_err($obj, 2);
    }
    return json_string($obj);
}


/**
 * 过滤异常信息
 * @param Throwable $e
 * @param int|bool $trace
 * @return array
 * @throws
 */
function filter_err(Throwable $e, $trace = 0)
{
    $root = ROOT_PATH;
    $err['code'] = $e->getCode();
    $err['message'] = $e->getMessage();
    if (method_exists($e, 'getError')) {
        $err['error'] = $e->getError();
    }

    $file = $e->getFile();
    if (stripos($file, 'vendor') === false) {
        $err['file'] = str_replace($root, '/', $file);
        $err['file'] = str_replace('\\', '/', $err['file']);
        $err['file'] .= ' (' . $e->getLine() . ')';
    }
    if (method_exists($e, 'getLog')) {
        $log = $e->getLog();
        if (!is_null($log)) {
            $err['log'] = $log;
        }
    }
    if ($trace) {
        $err['trace'] = get_trace(9, DEBUG_BACKTRACE_PROVIDE_OBJECT);
    }
    return $err;
}

/**
 * @param int $limit
 * @param int $options DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS
 * @return array
 * @throws
 */
function get_trace(int $limit = 9, int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT)
{
    $traces = debug_backtrace($options, $limit);
    unset($traces[0]);
    $root = ROOT_PATH;
    foreach ($traces as $i => $trace) {
        $traceStr = '';
        if (isset($trace['file'])) {
            $trace['file'] = str_replace($root, '/', $trace['file']);
            $trace['file'] = str_replace('\\', '/', $trace['file']);
            $traceStr .= $trace['file'].' (' . $trace['line'] .'): ';
        }
        if (isset($trace['class'])) {
            $traceStr .= $trace['class'] . $trace['type'];
        }
        if (isset($trace['function'])) {
            $args = isset($trace['args']) ? json_string($trace['args']) : '';
            $args = trim($args, '[]');
            $traceStr .= $trace['function'] . '('.$args.')';
        }
        $traces[$i] = $traceStr;
    }
    return $traces;
}

if (!function_exists('posix_getpid')) {
    /**
     * Windows下的降级方案
     * @return false|int
     */
    function posix_getpid()
    {
        return getmypid();
    }
}

if (!function_exists('gzdecode')) {
    function gzdecode($data)
    {
        return $data;
    }
}

if (!function_exists('console_log')) {
	/**
	 * 向控制台输出日志
	 * @param ...$log
	 *
	 * 调用：console_log('aa', 'bb', 'cc');
	 * 输出：aa | bb | cc
	 */
	function console_log(...$log)
	{
		$logs = [];
		foreach ($log as $d) {
			if (is_string($d)) {
				$d = trim($d);
			}
			$logs [] = print_r($d, true);
		}
		echo PHP_EOL . join(' | ', $logs) . PHP_EOL;
	}
}

if (!function_exists('put_log')) {
	/**
	 * 写日志
	 * @param string $title 日志标题
	 * @param mixed $data 任意类型的数据
	 * @param string $fileName 文件名，不含路径 和 扩展名，如 "mylog"
	 */
	function put_log($title, $data, $fileName = '')
	{
		$content = '[' . $title . '] ' . date('Y-m-d H:i:s') . ' ==================== ' . PHP_EOL;
		$content .= var_export($data, true) . PHP_EOL . PHP_EOL;

		$fileName = $fileName ?: 'log';
		$fileName = __DIR__ . '/../log/' . $fileName . '.txt';

		file_put_contents($fileName, $content, FILE_APPEND);
	}
}

if (!function_exists('get_incr_id')) {
	/**
	 * 客户端设备上线时取号
	 * @return int
	 */
	function get_incr_id()
	{
		return redis()->incrBy("1bom_incr_id", 1);
	}
}

if (!function_exists('redis')) {
	/**
	 * @return Redis|Predis\Client|null
	 * @throws Exception
	 */
	function redis()
	{
		static $redis;
		if ($redis) {
			return $redis;
		}
		$host = '127.0.0.1';
		$port = 6379;
		$password = '123456';
		$database = 0;
		$prefix = 'x:';
		if (extension_loaded("redis")) {
			$redis = new Redis();
			$redis->connect($host, $port);
			if ($redis->auth($password)) {
				$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
			} else {
				throw new Exception('Redis 密码错误');
			}
		} else {
			$redis = new Predis\Client("tcp://$host:$port", [
				'prefix' => $prefix,
				'parameters' => ['password' => $password, 'database' => $database],
			]);
		}
		return $redis;
	}
}
